﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using agvcontroller.Common;
using agvcontroller.Common.DataBase;
using agvcontroller.Control;
using agvcontroller.Log;

namespace agvcontroller.Process
{
    public delegate void deleAGVCDisplayLog(string msg);

    class CAGVController : IDisposable
    {
        public event deleAGVCDisplayLog onDisplayLog;

        CCommonInfo _CommonInfo = new CCommonInfo();
        public CCommonInfo CommonInfo
        {
            get { return _CommonInfo; }
        }

        private bool disposed = false;

        CAGVCDB AGVCDB;

        CVehicleDic _VehicleDic;
        public CVehicleDic VehicleDic
        {
            get { return _VehicleDic; }
        }

        CTerminalDic _TerminalDic;
        public CTerminalDic TerminalDic
        {
            get { return _TerminalDic; }
        }

        CChargerDic _ChargerDic;
        public CChargerDic ChargerDic
        {
            get { return _ChargerDic; }
        }

        CHostDic _HostDic;
        public CHostDic HostDic
        {
            get { return _HostDic; }
        }

        CJobManager _JobManager = CJobManager.getInstance();
        public CJobManager JobManager
        {
            get { return _JobManager; }
        }
        CTrafficManager _TrafficManager = CTrafficManager.getInstance();
        public CTrafficManager TrafficManager
        {
            get { return _TrafficManager; }
        }
        CRouteManager _RouteManager = CRouteManager.getInstance();
        public CRouteManager RouteManager
        {
            get { return _RouteManager; }
        }

        Logger Log = new Logger("AGVController");

        private static CAGVController uniqueInstance;

        public static CAGVController getInstance()
        {
            if (uniqueInstance == null)
            {
                uniqueInstance = new CAGVController();
            }
            return uniqueInstance;
        }

        public CAGVController()
        {
            InitModule();
        }

        public int InitModule()
        {
            AGVCDB = CAGVCDB.getInstance();

            _VehicleDic = CVehicleDic.getInstance();
            _TerminalDic = CTerminalDic.getInstance();
            _ChargerDic = CChargerDic.getInstance();
            _HostDic = CHostDic.getInstance();

            _JobManager.StartJobProcess();

            LogMsg(string.Format("Initialize Module."), enumLogLevel.INFO);

            return CReturnCode.SUCCESS;
        }

        public int GetDataFromDB()
        {


            return CReturnCode.SUCCESS;
        }

        void LogMsg(string log, enumLogLevel level, bool displayLog = false)
        {
            Log.LogMsg(log,level);

            if(displayLog)
            onDisplayLog(log);
        }

        public void RegisterEvent()
        {
            foreach (KeyValuePair<int,CVehicle> vehicle in VehicleDic)
            {
                vehicle.Value.onReportAlarm += new deleReportAlarm(vehicle_onReportAlarm);
                vehicle.Value.onReportCommunication += new deleReportCommunication(vehicle_onReportCommunication);
                vehicle.Value.onReportConnection += new deleReportConnection(vehicle_onReportConnection);
                vehicle.Value.onReportOperation += new deleReportOperation(vehicle_onReportOperation);
                vehicle.Value.onReportPosition += new deleReportPosition(vehicle_onReportPosition);
                vehicle.Value.onReportVehicleInfo += new deleReportVehicleInfo(vehicle_onReportVehicleInfo);
                vehicle.Value.onRequestRoute += new deleRequestRoute(vehicle_onRequestRoute);
                vehicle.Value.onAcceptVehicleJob += new deleAcceptVehicleJob(Value_onAcceptVehicleJob);
                vehicle.Value.onRejectVehicleJob += new deleRejectVehicleJob(Value_onRejectVehicleJob);
                vehicle.Value.onCompletedVehicleJob += new deleCompletedVehicleJob(Value_onCompletedVehicleJob);
                vehicle.Value.onReportInterlockSignal += new deleReportInterlockSignal(Value_onReportInterlockSignal);
                Log.Info(string.Format("Regist Event."));
            }

            foreach (KeyValuePair<int, CCharger> charger in ChargerDic)
            {

            }

            foreach (KeyValuePair<int, CTerminal> terminal in TerminalDic)
            {
                terminal.Value.onRequestJob += new deleTerminalRequestJob(Value_onRequestJob);
                terminal.Value.onCancelJob +=new deleTerminalCancelJob(Value_onCancelJob);
            }

            foreach (KeyValuePair<int, CHost> host in _HostDic)
            {

            }
        }       

        void Value_onCompletedVehicleJob(object sender, string vehiclejobId)
        {
            LogMsg(string.Format("Event Command Complete from {0}. Vehicle Job ID : {1} ", ((CVehicle)sender).Name, vehiclejobId), enumLogLevel.INFO);

        }

        void Value_onRejectVehicleJob(object sender, string vehiclejobId)
        {
            LogMsg(string.Format("Event Reject Command from {0}. , Vehicle Job ID: {1}", ((CVehicle)sender).Name, vehiclejobId), enumLogLevel.INFO);
        }

        void Value_onAcceptVehicleJob(object sender, string vehiclejobId)
        {
            CJob job = _JobManager.GetJobbyVehicleJobID(vehiclejobId);

            if (job == null)
            {
                //Alarm
                return;
            }

            if (job.State == enumJobState.SENDJOB)
                job.State = enumJobState.ACCEPTJOB;

            LogMsg(string.Format("Event Accept Comment from {0}.", ((CVehicle)sender).Name), enumLogLevel.INFO);
        }

        void Value_onCancelJob(object sender, int jobNo)
        {
            LogMsg(string.Format("Event Cancel Job from {0}. , Job No : {1}", ((CVehicle)sender).Name, jobNo, jobNo), enumLogLevel.INFO);

        }

        void Value_onRequestJob(object sender, int jobNo)
        {
            LogMsg(string.Format("Event Request Job from {0}. , Job No : {1} ", ((CVehicle)sender).Name, jobNo), enumLogLevel.INFO);
        }

        void Value_onReportInterlockSignal(object sender, List<int> interlock)
        {
            LogMsg(string.Format("Event Report Interlock Signal from {0}. ", ((CVehicle)sender).Name), enumLogLevel.INFO);

        }

        void vehicle_onRequestRoute(object sender, int cmdId)
        {
            LogMsg(string.Format("Event Request Route Info from {0}. Command ID : {1} ", ((CVehicle)sender).Name, cmdId), enumLogLevel.INFO);
        }

        void vehicle_onReportVehicleInfo(object sender, stVehicleInfo info)
        {
            LogMsg(string.Format("Event Report Vehicle Info from {0}.", ((CVehicle)sender).Name), enumLogLevel.INFO);

        }

        void vehicle_onReportPosition(object sender, int nodeno)
        {
            //Check Invalid Node
            if (!_RouteManager.NodeDic.IsInvalidNodeNo(nodeno))
            {
                //alarm
            }

            //CheckTraffic

            //UpdateNodeInfo
            _RouteManager.UpdateNodeInfo((CVehicle)sender, nodeno);
            LogMsg(string.Format("Event Report Position from {0}. Node ID {1}", ((CVehicle)sender).Name, nodeno), enumLogLevel.INFO);
        }

        void vehicle_onReportOperation(object sender, enumOperation operation)
        {
            LogMsg(string.Format("Event Report Operation from {0}. operation {1}", ((CVehicle)sender).Name, operation.ToString()), enumLogLevel.INFO);
        }

        void vehicle_onReportConnection(object sender, enumConnect connect)
        {
            LogMsg(string.Format("Event Report Connection from {0}. connect {1}", ((CVehicle)sender).Name, connect.ToString()), enumLogLevel.INFO);

        }

        void vehicle_onReportCommunication(object sender, enumCommnication communication)
        {
            LogMsg(string.Format("Event Report Communication from {0}. communication {1}", ((CVehicle)sender).Name, communication.ToString()), enumLogLevel.INFO);
        }

        void vehicle_onReportAlarm(object sender, int alarmId)
        {
            LogMsg(string.Format("Event Report Alarm from {0}. Alarm ID {1}", ((CVehicle)sender).Name, alarmId.ToString()), enumLogLevel.INFO);

        }

        public void Dispose()
        {
            Dispose(true);
 
            // 가비지컬렉터가 수동으로 작동되지 않게 설정한다.
            GC.SuppressFinalize(this);
        }

        protected virtual void Dispose(bool disposing)
        {
            // Check to see if Dispose has already been called.
            if (!this.disposed)
            {
                // If disposing equals true, dispose all managed
                // and unmanaged resources.
                if (disposing)
                {
                }

                // Note disposing has been done.
                disposed = true;
            }
        }

        ~CAGVController()
        {
            Dispose(false);
        }
    }
}
